package com.eyes.ds;

import android.app.Presentation;
import android.content.Context;
import android.content.DialogInterface;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
import android.view.View;

import android.view.Menu;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;

import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import com.eyes.ds.adapter.PhotoAdapter;
import com.eyes.ds.display.Showoff;
import com.eyes.ds.display.VideoShow;
import com.google.android.material.navigation.NavigationView;

import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener, AdapterView.OnItemClickListener {

    public final static String TAG = "MainActivity";

    // List of all currently visible presentations indexed by display id.
    private final SparseArray<Showoff> mActiveShowoffs = new SparseArray<>();
    private final SparseArray<VideoShow> mActiveVideos = new SparseArray<>();

    // List of presentation contents indexed by displayId.
    // This state persists so that we can restore the old presentation
    // contents when the activity is paused or resumed.
    private SparseArray<Showoff.ShowContents> mSavedPresentationContents;
    // Key for storing saved instance state.
    private static final String SHOWOFF_KEY = "show_off";

    private DisplayManager mDisplayManager;

    private SparseArray<Display> displays = new SparseArray<>();

    private PhotoAdapter photoAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        // Restore saved instance state.
        if (savedInstanceState != null) {
            mSavedPresentationContents = savedInstanceState.getSparseParcelableArray(SHOWOFF_KEY);
        } else {
            mSavedPresentationContents = new SparseArray<>();
        }

        // Get the display manager service.
        mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
        // append displays
        Display[] ds = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
        String info = "";
        for(Display d : ds) {
            displays.append(d.getDisplayId(),d);
            info += d.getDisplayId()+"--"+d.getName()+"\n";
        }

        Log.w(TAG,"there are "+displays.size()+" displays");
        Toast.makeText(this,"there are "+displays.size()+" presentation displays in this devices"+info,Toast.LENGTH_LONG).show();

        GridView gv = findViewById(R.id.gv_photos);
        photoAdapter = new PhotoAdapter(this,R.layout.photoholder, Arrays.asList(Showoff.PHOTOS));
        gv.setAdapter(photoAdapter);
        gv.setOnItemClickListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Restore presentations from before the activity was paused.
        for (int i = 0; i < displays.size(); i++) {
            final Display display = displays.valueAt(i);
            final Showoff.ShowContents contents =
                    mSavedPresentationContents.get(display.getDisplayId());
            if (contents != null) {
                showPresentation(display, contents);
            }
        }
        mSavedPresentationContents.clear();

        // Register to receive events from the display manager.
        mDisplayManager.registerDisplayListener(mDisplayListener, null);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Unregister from the display manager.
        mDisplayManager.unregisterDisplayListener(mDisplayListener);

        // Dismiss all of our presentations but remember their contents.
        Log.d(TAG, "Activity is being paused.  Dismissing all active presentation.");
        for (int i = 0; i < mActiveShowoffs.size(); i++) {
            Showoff presentation = mActiveShowoffs.valueAt(i);
            int displayId = mActiveShowoffs.keyAt(i);
            mSavedPresentationContents.put(displayId, presentation.mContents);
            presentation.dismiss();
        }
        mActiveShowoffs.clear();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // Be sure to call the super class.
        super.onSaveInstanceState(outState);
        outState.putSparseParcelableArray(SHOWOFF_KEY, mSavedPresentationContents);
    }

    /**
     * Sets the display mode of the {@link Presentation} on the specified display
     * if it is already shown.
     */
    private void setPresentationDisplayMode(Display display, int displayModeId) {
        final int displayId = display.getDisplayId();
        Showoff presentation = mActiveShowoffs.get(displayId);
        if (presentation == null) {
            return;
        }

        presentation.setPreferredDisplayMode(displayModeId);
    }

    private int getRandomMode(Display.Mode[] modes) {
        return (int) (modes.length*Math.random());
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }


    /**
     * Listens for displays to be added, changed or removed.
     * We use it to update the list and show a new {@link Presentation} when a
     * display is connected.
     *
     * Note that we don't bother dismissing the {@link Presentation} when a
     * display is removed, although we could.  The presentation API takes care
     * of doing that automatically for us.
     */
    private final DisplayManager.DisplayListener mDisplayListener =
            new DisplayManager.DisplayListener() {
                @Override
                public void onDisplayAdded(int displayId) {
                    Log.d(TAG, "Display #" + displayId + " added.");
                    updateDisplays();
                }

                @Override
                public void onDisplayChanged(int displayId) {
                    Log.d(TAG, "Display #" + displayId + " changed.");
                    updateDisplays();
                }

                @Override
                public void onDisplayRemoved(int displayId) {
                    Log.d(TAG, "Display #" + displayId + " removed.");
                    updateDisplays();
                }
            };

    private void updateDisplays() {
        displays.clear();
        Display[] ds = mDisplayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
        for(Display d : ds) {
            displays.append(d.getDisplayId(),d);
        }
        Log.d(TAG, "There are currently " + displays.size() + " displays connected.");
        for (Display display : ds) {
            Log.d(TAG, "  " + display);
        }
    }

    /**
     * Listens for when presentations are dismissed.
     */
    private final DialogInterface.OnDismissListener mOnDismissListener =
            new DialogInterface.OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialog) {
                    Presentation presentation = (Presentation) dialog;
                    int displayId = presentation.getDisplay().getDisplayId();
                    Log.d(TAG, "Presentation on display #" + displayId + " was dismissed.");
                    mActiveShowoffs.delete(displayId);
                    photoAdapter.notifyDataSetChanged();
                }
            };


    /**
     * Shows a {@link Presentation} on the specified display.
     */
    private void showPresentation(final Display display, final Showoff.ShowContents contents) {
        final int displayId = display.getDisplayId();
        if (mActiveShowoffs.get(displayId) != null) {
            return;
        }

        Log.d(TAG, "Showing presentation photo #" + contents.photo
                + " on display #" + displayId + ".");

        Showoff presentation = new Showoff(this, display, contents);
        presentation.show();
        presentation.setOnDismissListener(mOnDismissListener);
        mActiveShowoffs.put(displayId, presentation);
    }

    /**
     * Shows a {@link Presentation} on the specified display.
     */
    private void showVideo(final Display display, final String url) {
        final int displayId = display.getDisplayId();
        if (mActiveShowoffs.get(displayId) != null) {
            return;
        }

        VideoShow presentation = new VideoShow(this, display, url);
        presentation.show();
        presentation.setOnDismissListener(mOnDismissListener);
        mActiveVideos.put(displayId, presentation);
    }

    /**
     * Hides a {@link Presentation} on the specified display.
     */
    private void hidePresentation(Display display) {
        final int displayId = display.getDisplayId();
        Showoff presentation = mActiveShowoffs.get(displayId);
        VideoShow videoShow = mActiveVideos.get(displayId);
        if (presentation == null && videoShow == null) {
            return;
        }

        Log.d(TAG, "Hiding presentation on display #" + displayId + ".");
        if (presentation!=null) {
            presentation.dismiss();
            mActiveShowoffs.delete(displayId);
        }
        if (videoShow!=null) {
            videoShow.dismiss();
            mActiveVideos.delete(displayId);
        }

    }


    Timer timer = null;
    TimerTask task = null;
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        if(displays.size()>0) {
            final Display toDisplay = displays.valueAt(0);
            final Display.Mode[] modes;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                modes = toDisplay.getSupportedModes();
                setPresentationDisplayMode(toDisplay,getRandomMode(modes));
            }

            hidePresentation(toDisplay);

            if (timer!=null) {
                timer.cancel();
                task.cancel();
                timer = null;
                task = null;
            }

            if (i == 0) {       // 第一个为测试视频

                timer = new Timer();
                task = new TimerTask() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                showVideo(toDisplay,"https://media.w3.org/2010/05/sintel/trailer.mp4");
                            }
                        });
                    }
                };
                timer.schedule(task, 50);

            } else {
                //display the view
                final Showoff.ShowContents contents = new Showoff.ShowContents(photoAdapter.getPhotos().get(i));

                timer = new Timer();
                task = new TimerTask() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                showPresentation(toDisplay,contents);
                            }
                        });
                    }
                };
                timer.schedule(task, 50);

            }

            photoAdapter.setPos(i);
            photoAdapter.notifyDataSetChanged();
        }
    }
}
